﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using kdRPG.Map;

namespace kdRPG
{
    class Player
    {
        #region Fields
        private Texture2D texture = null;
        private Vector2 position;
        private float xVel = 5;
        private float yVel = 8;

        private bool jumping = false;
        private bool falling = false;
        private int jumpCounter = 0;
        private int fallCounter = 0;
        private int totalJumpHeight = 16;

        private int screenWidth;
        private int screenHeight;
        private const int playerWidth = 32;
        private const int playerHeight = 64;

        private KeyboardState previousState;
        private KeyboardState currentState;
        private int move = 0;
        private enum MoveState {Up, Right, Down, Left};

        private bool isColliding = false;
        private Rectangle collisionRect;
        private Tile collidingTile;
        private float prevX, prevY;
        #endregion

        #region Constructors
        public Player(Texture2D texture, Vector2 position, int screenWidth, int screenHeight){
            this.texture = texture;
            this.position = position;
            this.screenWidth = screenWidth;
            this.screenHeight = screenHeight;   
        }
        #endregion

        #region Methods
        public void update(GameTime gameTime){

            currentState = Keyboard.GetState();
            collisionRect = new Rectangle((int)position.X, (int)position.Y, playerWidth, playerHeight);
            // Moving the character around with the keys
            if (currentState.IsKeyDown(Keys.Right)){
                position.X += xVel;
                move = (int) MoveState.Right;
            }
            else if (currentState.IsKeyDown(Keys.Left)){
                position.X -= xVel;
                move = (int) MoveState.Left;
            }
            if (currentState.IsKeyDown(Keys.Up)){
                //position.Y -= yVel;
                move = (int) MoveState.Up;
            }
            else if (currentState.IsKeyDown(Keys.Down)){
                //position.Y += yVel;
                move = (int) MoveState.Down;
            }

            // Checking for collision and offsetting the Y value if the character is above the solid tile
            if (isColliding)
            {
                if (collidingTile.isSolid())
                {
                    int tileY = collidingTile.CollisionRectangle.Y;
                    int tileX = collidingTile.CollisionRectangle.X;
                    // Bottom collision
                    if (tileY + collidingTile.Height < prevY + 32)
                    {
                        position.Y = tileY + collidingTile.Height;
                        jumping = false;
                        collidingTile.isHit = true;
                        jumpCounter = 0;
                        falling = true;
                    }
                    // Top collision
                    else
                    {
                        position.Y = tileY - playerHeight + yVel;
                        falling = false;
                        fallCounter = 0;
                    }

                    // Sides collision (not working)
                    
                    if (tileX >= prevX - playerWidth)
                    {
                        position.X = tileX - playerWidth;
                    }
                    else if (tileX + collidingTile.Width < prevX)
                    {
                        position.X = tileX + Width;
                    }
                }
            }
            // Jumping Logic
            if (!jumping)
            {
                // Gravity
                if(!isColliding) 
                    position.Y += yVel;

                if(!falling){
                    if (currentState.IsKeyDown(Keys.Space) && previousState.IsKeyUp(Keys.Space))
                    {
                        jumpCounter = 0;
                        jumping = true;
                    }
                }
            }
            else
                continueJump();
            if (falling)
                continueFall();

            // Boundary Checking for the outside edges of the screen
            if (position.X < 0)
                position.X = 0;
            else if (position.X > screenWidth - playerWidth)
                position.X = screenWidth - playerWidth;
            if (position.Y < 0)
                position.Y = 0;
            else if (position.Y > screenHeight - playerHeight)
                position.Y = screenHeight - playerHeight;


            previousState = currentState;
            isColliding = false;
            prevY = position.Y;
            prevX = position.X;
        }

        public void draw(SpriteBatch spriteBatch){
            if(isColliding)
                spriteBatch.Draw(texture, position, new Rectangle(move * playerWidth, 0, playerWidth, playerHeight), Color.Red);
            else
                spriteBatch.Draw(texture, position, new Rectangle(move * playerWidth, 0, playerWidth, playerHeight), Color.White);
        }

        private void continueJump()
        {
            if (jumpCounter < totalJumpHeight)
            {
                position.Y -= yVel;
                jumpCounter++;
            }
            else
            {
                jumping = false;
                fallCounter = 0;
                falling = true;
            }
        }

        private void continueFall()
        {
            if (fallCounter < totalJumpHeight)
            {
                fallCounter++;
            }
            else
            {
                falling = false;
                fallCounter = 0;
            }
        }

        public void isNowColliding(Tile collidingTile)
        {
            isColliding = true;
            this.collidingTile = collidingTile;
        }
        #endregion

        #region Properties
        public Texture2D Texture {
            get { return texture; }
        }

        public Vector2 Position{
            get { return position; }
        }

        public int Width{
            get { return playerWidth; }
        }

        public int Height{
            get { return playerHeight; }
        }

        public Rectangle CollisionRectangle
        {
            get { return collisionRect; }
        }
        #endregion
    }
}
